/*****************************************************
	DataFlashTest1.c Joe Pardue September 24, 2010

	Pretest DataFlash functions before writing the 
	Data Logger
******************************************************/

// I HATE LICENSES LIKE THIS >>BUT<< I've been told that without
// the license then the work is automatically copyrighted in my name
// since my purpose is to educate (and learn), I want the code to be 
// used by whoever wants to use it to learn something. If you like it, 
// then visit my website www.smileymicros.com and buy something.

/*
 *  BSD License
 *  -----------
 *
 *  Copyright (c) 2008, Smiley Micros, All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer. 
 *   
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution. 
 *   
 *  - Neither the name of the Smiley Micros nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission. 
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *  ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 */

// And to further cover my butt, let me add that if you use this software
// it will destroy whatever machine you use it on and kill anyone in a one 
// kilometer radius. So don't even consider using it for any reason whatsoever!

/*****************************************************
	Include files
******************************************************/
#include <stdlib.h>  // for rand() and itoa()
#include <avr\pgmspace.h>

// Be sure and select your device
// Butterfly, Arduino (board), or Atmega644
#include "Device\device.h"

// The SmileyUSART was include for debugging
// SmileyUSART.h uses define.h
// to calculate the baud rate
#include "USART\SmileyUSART.h"

#include "SPI\SPI.h"
#include "DataFlash\dataflash.h"

/*****************************************************
	Defines
******************************************************/

/*****************************************************
	Global variables
******************************************************/

/*****************************************************
	Constants in PROGMEM
******************************************************/
// identify() loads this and from device.h
// the device name and outputs to the UART
const char PROGRAM[] PROGMEM = "DataFlashTest1 - ";
const char VERSION[] PROGMEM = "1.23 \r";

// ?TODO: WHY WON'T THIS GO IN DEVICES.H?
// Used by the main module to identify the device
#if defined(Arduino)
const char DEVICE_NAME[] PROGMEM = "Arduino ";
#elif defined (Butterfly)
const char DEVICE_NAME[] PROGMEM = "Butterfly ";
#elif defined (BeAVR40)
const char DEVICE_NAME[] PROGMEM = "BeAVR40 ";
#else
const char DEVICE_NAME[] PROGMEM = "DEVICE_NAME UNDEFINED";
#endif

/*****************************************************
	Function declarations
******************************************************/

void identify(void);
void show_status(void);
void buffer_test(void);
void flash_test(void);
void show_bits(uint8_t);
void data_logger_fake_test(void);





/*
struct pwm{
	int pulseFreq;
	unsigned pulseWidth;
};


// Declare a function with struct pointers as parameters
struct pwm widestPWM(struct pwm *, struct pwm *, struct pwm *);

// Define it
struct pwm widestPWM(struct pwm *p1, struct pwm *p2, struct pwm *p3)
{
	if(p1->pulseWidth > p2->pulseWidth) 
	{
		if (p1->pulseWidth > p3->pulseWidth) return *p1;
	}
	else if (p2->pulseWidth > p3->pulseWidth) return *p2;
	return *p3;
}

*/

// Declare the structure the room meter
struct rm{
	uint8_t room_number;
	uint8_t lights_on_off;
	uint8_t temperature;
	uint8_t number_of_occupants;
	uint32_t date_time;
};


void convert_array_to_rm(struct rm *, uint8_t *);
void convert_rm_to_array(struct rm *, uint8_t *);

void report_data(struct rm *);



int main(void)
{	 

	identify();

	//df_spi_init();
	spi0_init_master();
	
	while(1)
	{
		// Read Status Register and show bits
		show_status();

		// Buffer test
		//buffer_test();

		// Flash test
		flash_test();

		// Data logger fake test
		//data_logger_fake_test();

		_delay_ms(15000);
	}

}

// This tests reading and writing a data logger
// data structure filled with fake data.
void data_logger_fake_test()
{
	//2147483647 is largest positive long integer
	struct rm room_13  = { 13, 1, 70, 3, 2147483647 };
	struct rm room_x;
	unsigned char array[8];

	// Send to DataFlash
	report_data(&room_13);

	convert_rm_to_array(&room_13, array);

	// Write array to buffer
	df_buffer_write_str (1, 0, 8, array);
	// Write buffer to flash
	df_buffer_to_page (1, 0);
	
	// Read from DataFlash

	// Read flash to buffer
	df_page_to_buffer (0, 1);
	// Read buffer into array
	df_buffer_read_str (1, 0, 8, array);

	convert_array_to_rm(&room_x, array);

	report_data(&room_x);



}

void convert_rm_to_array(struct rm *r, uint8_t *array)
{
	array[0] = r->room_number;
	array[1] = r->lights_on_off;
	array[2] = r->temperature;
	array[3] = r->number_of_occupants;

	array[4] = (uint8_t)(r->date_time>>24);
	array[5] = (uint8_t)(r->date_time>>16);
	array[6] = (uint8_t)(r->date_time>>8);
	array[7] = (uint8_t)r->date_time;
}

void convert_array_to_rm(struct rm *r, uint8_t *array)
{
	r->room_number = array[0];
	r->lights_on_off = array[1];
	r->temperature = array[2];
	r->number_of_occupants = array[3];

	r->date_time = ((uint32_t)array[4] << 24);
	r->date_time += ((uint32_t)array[5] << 16);
	r->date_time += ((uint32_t)array[6] << 8);
	r->date_time += ((uint32_t)array[7]);
}


void report_data(struct rm *dl)
{
	// 
	char temp[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0};


	//uart_send_byte(;

	uart_send_string("\rdl->room_number: ");
	itoa(dl->room_number,temp,10);
	uart_send_string(temp);

	uart_send_string("\rdl->lights_on_off: ");
	itoa(dl->lights_on_off,temp,10);
	uart_send_string(temp);

	uart_send_string("\rdl->temperature: ");
	itoa(dl->temperature,temp,10);
	uart_send_string(temp);

	uart_send_string("\rdl->number_of_occupants: ");
	itoa(dl->number_of_occupants,temp,10);
	uart_send_string(temp);
	
	// note: using ltoa
	uart_send_string("\rdl->date_time: ");
	ltoa(dl->date_time,temp,10);
	uart_send_string(temp);
	
/*	uart_send_string("\rdl->: ");
	itoa(dl->,temp,10);
	uart_send_string(temp);
*/
}


void flash_test()
{
	//uint8_t temp = 0x55;
	unsigned char array1[] = "Hello, World!";
	unsigned char array2[] = "Goodbye ya'll";

	// Before
	uart_send_string("\rBefore array1:\r");
	uart_send_string((const char *)array1);
	uart_send_string("\rBefore array2:\r");
	uart_send_string((const char *)array2);

	// Write array to buffer
	df_buffer_write_str (1, 0, 13, array1);
	// Write buffer to flash
	df_buffer_to_page (1, 0);
	
	// Read flash to buffer
	df_page_to_buffer (0, 1);
	// Read buffer into array
	df_buffer_read_str (1, 0, 13, array2);

	// After
	uart_send_string("\rAfter array1:\r");
	uart_send_string((const char *)array1);
	uart_send_string("\rAfter array2:\r");
	uart_send_string((const char *)array2);
}

void buffer_test()
{
	//uint8_t temp = 0x55;
	unsigned char array1[] = "Hello, World!";
	unsigned char array2[] = "Goodbye ya'll";

	// Before
	uart_send_string("\rBefore array1:\r");
	uart_send_string((const char *)array1);
	uart_send_string("\rBefore array2:\r");
	uart_send_string((const char *)array2);
	//show_bits(temp);

	// Write a byte
	//buffer_write_enable (1, 0);
	//Buffer_Write_Byte (1, 0, temp);
	df_buffer_write_str (1, 0, 13, array1);
	
	// Read it back
	//temp = Buffer_Read_Byte (1, 0);
	df_buffer_read_str (1, 0, 13, array2);

	// After
	uart_send_string("\rAfter array1:\r");
	uart_send_string((const char *)array1);
	uart_send_string("\rAfter array2:\r");
	uart_send_string((const char *)array2);
}





/*****************************************************
	Identify the program, device, and version
******************************************************/
// Send program name, device, and revision
// out on the UART
void identify()
{
	uart_send_stringP(PROGRAM);
	uart_send_stringP(DEVICE_NAME);
	uart_send_stringP(VERSION);
}


// TODO: compiler issues a warning for using int8_t
// but no warning for char. BUT they are supposed 
// to be the same.
void show_status()
{
  	uint8_t status = 0;
	//int8_t array[] = {0,0,0,0,0,0,0,0,0,0,0};
	char array[] = {0,0,0,0,0,0,0,0,0,0,0};
	
	// Get the status
	status = df_read_status(); 

	uart_send_string("\rStatus:\r");
	show_bits(status);

	uart_send_string("\rdf_page_bits: ");
	itoa((int16_t)df_page_bits,array,10);
	uart_send_string(array);
	uart_send_string("\rdf_page_size: ");
	itoa((int16_t)df_page_size,array,10);
	uart_send_string(array);
	uart_send_byte('\r');
}

void show_bits(uint8_t byte)
{
  	// Show each bit
  	for (int i=7; i>=0; i--)
  	{
    	if(!!(byte & (1 << i)))
		{
			uart_send_bit(1);
    	}
		else
		{
			uart_send_bit(0);
		}
  	}
	uart_send_string("\r>----------<\r");
}
